package com.gzhu.knowledgeAdmin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gzhu.knowledgeAdmin.common.constant.RoleType;
import com.gzhu.knowledgeAdmin.common.helper.MemuHelper;
import com.gzhu.knowledgeAdmin.common.helper.PermissionHelper;
import com.gzhu.knowledgeAdmin.common.model.Option;
import com.gzhu.knowledgeAdmin.common.utils.UserInfoUtils;
import com.gzhu.knowledgeAdmin.common.vo.DoAssignVo;
import com.gzhu.knowledgeAdmin.common.vo.MenuVO;
import com.gzhu.knowledgeAdmin.dao.PermissionMapper;
import com.gzhu.knowledgeAdmin.entity.*;
import com.gzhu.knowledgeAdmin.service.PermissionService;
import com.gzhu.knowledgeAdmin.service.RolePermissionService;
import com.gzhu.knowledgeAdmin.service.XtyhService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2020-01-12
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private XtyhService xtyhService;


    //给角色分配权限
    @Override
    @Transactional
    public void saveRolePermissionRealtionShip(DoAssignVo doAssignVo) {
        String roleId = doAssignVo.getRoleId();
        List<String> permissionIds = doAssignVo.getPermissionId();

        rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));


        List<RolePermission> rolePermissionList = new ArrayList<>();
        for (String permissionId : permissionIds) {
            if (StringUtils.isEmpty(permissionId)) continue;

            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            rolePermissionList.add(rolePermission);
        }
        rolePermissionService.saveBatch(rolePermissionList);
    }


    //根据用户id获取用户权限值
    @Override
    public List<String> selectPermissionValueByUserId(Integer id) {

        List<String> selectPermissionValueList = null;
        boolean isSysAdmin = this.isSysAdmin(id);
        if (isSysAdmin) {
            //如果是系统管理员，获取所有权限
            selectPermissionValueList = baseMapper.selectAllPermissionValue();
        } else {
            selectPermissionValueList = baseMapper.selectPermissionValueByUserId(id);
        }

        return selectPermissionValueList;
    }

    private boolean isSysAdmin(Integer id) {
        Xtyh user = xtyhService.getById(id);
        return user.getYhlx() == 1;
    }


    /**
     * 查询所有菜单
     *
     * @return
     */
    @Override
    public List<Permission> queryAllMenuGuli() {

        //1 查询菜单表所有数据
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("sort");
        List<Permission> permissionList = baseMapper.selectList(wrapper);

        // 所有父菜单id
        Set<String> parentIds = permissionList.stream()
                .map(Permission::getPid)
                .collect(Collectors.toSet());
        // 所有菜单id
        Set<String> menuIds = permissionList.stream()
                .map(Permission::getId)
                .collect(Collectors.toSet());

        // 2. 求差集，得到 parentIds 中 menuIds 没有的元素
        List<String> rootIds = CollectionUtil.subtractToList(parentIds, menuIds);

        List<Permission> list = new ArrayList<>();
        // 为每个最顶级的菜单设置子菜单
        for (String rootId : rootIds) {
            list.addAll(recurMenus(rootId, permissionList)); // 递归
        }
        return list;
    }

    /**
     * 递归生成菜单列表
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return
     */
    private List<Permission> recurMenus(String parentId, List<Permission> menuList) {
        return CollectionUtil.emptyIfNull(menuList)
                .stream()
                .filter(menu -> menu.getPid().equals(parentId))
                .map(entity -> {
                    List<Permission> children = recurMenus(entity.getId(), menuList);
                    entity.setChildren(children);
                    return entity;
                }).collect(Collectors.toList());
    }

    //============递归删除菜单==================================
    @Override
    @Transactional
    public void removeChildByIdGuli(String id) {
        //1 创建list集合，用于封装所有删除菜单id值
        List<String> idList = new ArrayList<>();
        //2 向idList集合设置删除菜单id
        this.selectPermissionChildById(id, idList);
        //把当前id封装到list里面
        idList.add(id);

        // 先删除角色菜单表相关数据
        rolePermissionService.removeBatchByPermissionIds(idList);

        // 再删除菜单表数据
        baseMapper.deleteBatchIds(idList);
    }

    @Override
    public void updatePermissionById(Permission permission) {

        UpdateWrapper<Permission> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", permission.getId());
        // 如果修改后是菜单或者目录类型，则将权限值置为空
        if (permission.getType() == 1 || permission.getType() == 2) {
            wrapper.set("permission_value", null);
        } else {
            // 否则将路径置为空
            wrapper.set("path", null);
        }

        baseMapper.update(permission, wrapper);
    }

    /**
     * 菜单下拉列表
     *
     * @return
     */
    @Override
    public List<Option> listPermissionOptions() {

        //1 查询菜单表所有数据
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("sort");

        User currentUser = UserInfoUtils.getCurrentUser();
        Integer userId = currentUser.getUserId();
        List<Permission> permissionList = null;
        // 系统管理员查询全部
        if(RoleType.SYS_ADMIN==currentUser.getYhlx()){
            permissionList = baseMapper.selectList(wrapper);
        }else {
            // 公司管理员只能查询自己拥有的菜单
            permissionList = baseMapper.selectPermissionByUserId(userId);
        }

        //2 把查询所有菜单list集合按照要求进行封装
        return recurMenuOptions("0", permissionList);
    }

    /**
     * 获取当前登录用户的菜单(不包括按钮)
     *
     * @return
     */
    @Override
    public List<MenuVO> curUserPermissionVoList() {

        // 获取当前登录用户
        User currentUser = UserInfoUtils.getCurrentUser();
        Integer userId = currentUser.getUserId();

        List<Permission> permissionList;
        // 如果是超级管理员，则查出所有菜单
        if (RoleType.SYS_ADMIN == currentUser.getYhlx()) {
            QueryWrapper<Permission> wrapper = new QueryWrapper<>();
            wrapper.ne("type", 3);
            wrapper.orderByAsc("sort");
            permissionList = baseMapper.selectList(wrapper);

        } else {
            // 否则只查出自己的菜单
            permissionList = baseMapper.selectPermissionNoButtonByUserId(userId);
        }

        Set<String> parentIds = permissionList.stream()
                .map(Permission::getPid)
                .collect(Collectors.toSet());

        Set<String> menuIds = permissionList.stream()
                .map(Permission::getId)
                .collect(Collectors.toSet());

        List<String> rootIds = CollectionUtil.subtractToList(parentIds, menuIds); // 求差集，得到 parentIds 中 menuIds 没有的元素

        List<MenuVO> list = new ArrayList<>();
        for (String rootId : rootIds) {
            list.addAll(recurMenusVo(rootId, permissionList)); // 递归
        }
        return list;
    }

    private List<MenuVO> recurMenusVo(String rootId, List<Permission> permissionList) {
        return CollectionUtil.emptyIfNull(permissionList)
                .stream()
                .filter(menu -> menu.getPid().equals(rootId))
                .map(entity -> {
                    MenuVO menuVO = new MenuVO();
                    menuVO.setName(entity.getName());
                    menuVO.setPath(entity.getPath());
                    List<MenuVO> children = recurMenusVo(entity.getId(), permissionList);
                    menuVO.setChildren(children);
                    return menuVO;
                }).collect(Collectors.toList());
    }

    /**
     * 递归生成菜单下拉层级列表
     *
     * @param parentId       父级ID
     * @param permissionList 菜单列表
     * @return
     */
    private static List<Option> recurMenuOptions(String parentId, List<Permission> permissionList) {
        List<Option> menus = CollectionUtil.emptyIfNull(permissionList).stream()
                .filter(menu -> menu.getPid().equals(parentId))
                .map(menu -> new Option(menu.getId(), menu.getName(), recurMenuOptions(menu.getId(), permissionList)))
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
        return menus;
    }

    /**
     * 根据当前菜单id，查询菜单里面子菜单id，封装到list集合
     * @param id 当前菜单id
     * @param idList 结果list集合
     */
    private void selectPermissionChildById(String id, List<String> idList) {
        //查询菜单里面子菜单id
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.eq("pid", id);
        wrapper.select("id");
        List<Permission> childIdList = baseMapper.selectList(wrapper);
        //把childIdList里面菜单id值获取出来，封装idList里面，做递归查询
        childIdList.stream().forEach(item -> {
            //封装idList里面
            idList.add(item.getId());
            //递归查询
            this.selectPermissionChildById(item.getId(), idList);
        });
    }
}
